#!/usr/bin/env python3
# -*- coding:utf-8 -*-
# @Time: 2020/6/19  14:43
# @Author: 余浪人
# @email: yulangren520@gmail.com
import json, time
from django.http import HttpResponse
from functools import wraps
from public import accessor_ip
from public.redis_pool import conn
from tl_book.settings import NORMAL_AUTH_TIME, NORMAL_AUTH_FREQUENCY, FREEZE_TIME

'''
数据库说明：
    NormalAccess ： 正常访问
    FreezeAccess :  冻结访问
    ForbidAccess :  禁止访问
'''


def normal_auth(fun):
    '''
    正常访问监测
    :param fun:
    @first_time 最后访问时间
    @time 初次访问时间
    :return:
    '''

    @wraps(fun)
    def decorated(request, *args, **kwargs):
        ip = accessor_ip(request)
        result_bool = conn.hexists('NormalAccess', ip)
        if not result_bool: conn.hset('NormalAccess', ip, json.dumps({'visit': 1, 'first_time': time.time(), 'time': time.time()}))
        if result_bool:
            result_dict = json.loads(conn.hget('NormalAccess', ip))
            if (time.time() - result_dict['first_time']) < NORMAL_AUTH_TIME and result_dict['visit'] >= NORMAL_AUTH_FREQUENCY:
                result_dict['freeze_time'] = time.time()
                result = conn.hset('FreezeAccess', ip, json.dumps(result_dict))
                if result:conn.hdel('NormalAccess', ip)
                return HttpResponse(f'{ip}/访问过快，请求冻结！', status=403)  # todo 友好提示-响应
            result_dict['visit'] += 1
            if (time.time() - result_dict['first_time']) > NORMAL_AUTH_TIME:
                result_dict['visit'] = 1
                result_dict['time'] = time.time()
            result_dict['first_time'] = time.time()
            conn.hset('NormalAccess', ip, json.dumps(result_dict))
        return fun(request, *args, **kwargs)

    return decorated


def freeze_auth(fun):
    '''
    冻结访问监测
    :param fun:
    :return:
    '''

    @wraps(fun)
    def decorated(request, *args, **kwargs):
        ip = accessor_ip(request)
        result_bool = conn.hexists('FreezeAccess', ip)
        if result_bool:
            result_dict = json.loads(conn.hget('FreezeAccess', ip))
            if ((time.time() - result_dict['freeze_time']) / 60) < FREEZE_TIME: return HttpResponse(f'{ip}/访问过快，请求冻结！', status=403)  # todo 友好提示-响应
            conn.hdel('FreezeAccess', ip)
        return fun(request, *args, **kwargs)

    return decorated


def forbid_auth(fun):
    '''
    禁止访问监测
    :param fun:
    :return:
    '''

    @wraps(fun)
    def decorated(request, *args, **kwargs):
        ip = accessor_ip(request)
        result_bool = conn.hexists('ForbidAccess', ip)
        if result_bool: return HttpResponse(f'{ip}/禁止访问，请求禁止！', status=404)  # todo 友好提示-响应
        return fun(request, *args, **kwargs)

    return decorated
